﻿using System;
using System.Runtime.Serialization;
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
using XamlaApp.Interfaces;
using System.Xml.Linq;

namespace XamlaApp.ViewModels
{
    [DataContract]
    public class UIElementViewModel : BaseElementViewModel
    {

        private List<FrameworkElement> PositionBoundElementList { get; set; }
        public void RegisterPositionBoundElement(FrameworkElement element)
        {
            if (element == null) throw new ArgumentException("element");

            if (PositionBoundElementList == null) PositionBoundElementList = new List<FrameworkElement>();

            PositionBoundElementList.Add(element);
        }

        private List<IXamlaElement> ProjectionBoundElementList { get; set; }
        public void RegisterProjectionBoundElement(IXamlaElement element)
        {
            if (element == null) throw new ArgumentException("element");

            try
            {
                if (element.ElementProjection == null) throw new ArgumentException("element.ElementProjection");
            }
            catch (NullReferenceException)
            {
                throw new ArgumentException("element.ElementProjection");
            }

            if (ProjectionBoundElementList == null) ProjectionBoundElementList = new List<IXamlaElement>();
            ProjectionBoundElementList.Add(element);
        }

        private double _rotationZ;
        [DataMember]
        public double RotationZAmount
        {
            get { return _rotationZ; }
            set
            {

                _rotationZ = Math.Round(RotationBoundsCheck(value), 1);

                if (ProjectionBoundElementList != null)
                    foreach (var e in ProjectionBoundElementList)
                    {
                        e.ElementProjection.RotationZ = _rotationZ;
                    }
                PropertyChanging("RotationZAmount");
            }
        }

        private double _rotationX;
        [DataMember]
        public double RotationXAmount
        {
            get { return _rotationX; }
            set
            {
                _rotationX = Math.Round(RotationBoundsCheck(value), 1);
                if (ProjectionBoundElementList != null)
                foreach (var e in ProjectionBoundElementList)
                {
                    e.ElementProjection.RotationX = _rotationX;
                }
                PropertyChanging("RotationXAmount");
            }
        }

        private double _rotationY;
        [DataMember]
        public double RotationYAmount
        {
            get { return _rotationY; }
            set
            {
                _rotationY = Math.Round(RotationBoundsCheck(value), 1);
                if (ProjectionBoundElementList != null)
                foreach (var e in ProjectionBoundElementList)
                {
                    e.ElementProjection.RotationY = _rotationY;
                }
                PropertyChanging("RotationYAmount");
            }
        }

        private static double RotationBoundsCheck(double value)
        {
            if (value < -180) return -180;
            if (value > 180) return 180;
            return value;
        }
        private double _opacity = 1;
        [DataMember]
        public double Opacity
        {

            get { return _opacity; }
            set
            {
                if (value > 1) _opacity = 1;
                if (value < 0) _opacity = 0;
                _opacity = Math.Round(value, 2);
                PropertyChanging("Opacity");
            }
        }

        private double _left;
        [DataMember]
        public double Left
        {
            get { return _left; }
            set
            {
                _left = value;
                if (PositionBoundElementList != null)
                    foreach (var e in PositionBoundElementList)
                    {
                        Canvas.SetLeft(e, _left);
                    }
                PropertyChanging("Left");
            }
        }

        private double _top;
        [DataMember]
        public double Top
        {
            get { return _top; }
            set
            {
                _top = value;
                if (PositionBoundElementList != null)
                foreach (var e in PositionBoundElementList)
                {
                    Canvas.SetTop(e, _top);
                }
                PropertyChanging("Top");
            }
        }

        internal override void PostDeserializeActions()
        {
            //force these values to rebind
            base.PostDeserializeActions();
        }

        internal override System.Xml.Linq.XElement GenerateXaml(XElement element)
        {
            element.Add(new XAttribute("Opacity", Opacity),
                new XAttribute("Canvas.Left", Left),
                new XAttribute("Canvas.Top", Top),
                new XElement(element.Name + ".Projection",
                    new XElement("PlaneProjection",
                        new XAttribute("RotationX",RotationXAmount),
                        new XAttribute("RotationY", RotationYAmount),
                        new XAttribute("RotationZ", RotationZAmount))));
            return base.GenerateXaml(element);
        }

    }
}
